#ifndef __CORDET_H__
#define __CORDET_H__
/*============================================================================*/
/*                                                                            */
/* cordet.h                                                                   */
/*                                                                            */
/* This is an implementation of the algorithm for detecting the corners       */
/* in digital images that was developed at VSB-Technical University           */
/* of Ostrava. The theory of the algorithm and other details are available at */
/*                                                                            */
/* http://www.cs.vsb.cz/sojka/cordet/presentation.html                        */
/*                                                                            */
/* If you want just only to use the algorithm, you will simply call this      */
/* function "detectCorners". You should, however, understand what its         */
/* particular parameters exactly mean and how they should be set. You can     */
/* find the explanation as well as some practical advice in this file.        */
/* Please, read them carefully since only with having the parameters set      */
/* properly, you can achieve the best possible results of the detector.       */
/* As a first inspiration, I recommend to have a look at how the parameters   */
/* were set for the test program in "cortest.c". Along with this file, you    */
/* should obtain the script files ("test1.scr", "test2.scr", "test3.scr"      */
/* and some others) containing the values of parameters for the test images   */
/* that were published in the above mentioned URL and that you should obtain  */
/* with this file too.                                                        */
/* The simplest way how to check whether the values of the parameters are     */
/* suitable for your images is simply to have a look at the image with the    */
/* detected corners indicated in it. This method, however, is successful      */
/* only in not too complicated cases.                                         */
/* A much better approach is to do the following: (1) Take a typical image    */
/* you want to process and prepare the reference solution manually. In the    */
/* reference solution, all the points that you regard as corners should be    */
/* listed. (2) Adjust the parameters to such values that minimise the total   */
/* error of the detection. You may use e.g. the error defined in the above    */
/* mentioned www presentation. For evaluating the differences between the     */
/* reference solution and the solution obtained by the algorithm you can use  */
/* the program in the file "evaldet.c" that you should obtain along with this */
/* file. You can also use the program in "findpars.c" that directly           */
/* determines the optimal values of "angleThresh", "noiseGradSizeThreshshold",*/
/* and "apparenceThresh". Let it be pointed out that this method based        */
/* on minimising an error may be useful not only for our, but also for other  */
/* detectors since all detectors use some parameters that must be set.        */
/*                                                                            */
/* If you need some further assistance or if you have some comments, please   */
/* be so kind and contact me at "eduard.sojka@vsb.cz".                        */
/*                                                                            */
/* This version of implementation is from 26 May 2003. Please, contact me     */
/* if you read this message substantially later. I may be able to provide     */
/* you with a newer version.                                                  */
/*                                                                            */
/* (c) Eduard Sojka, 2003                                                     */
/*                                                                            */
/*============================================================================*/

int detectCorners(

    float *image_p,              /* The array containing the values of bright-*/
           /* ness. Please note that the values are represented as floats.    */
           /* Important: The algorithm does not detect the corners at the     */
           /* border of the image. The width of this border is halfMaskSize+1.*/
           /* This usually does not matter. If it could be a problem, place   */
           /* your image into a bigger one whose sizes are increased by       */
           /* 2*(halfMaskSize+1) in both directions. Have in mind this fact   */
           /* also if you are preparing the reference solution (see above).   */
           /* In noisy images, according to our experience, it is often useful*/
           /* to convolve the image with the Gaussian prior to the corner     */
           /* detection. The value of sigma=0.5 proved to be suitable for     */
           /* most images. You should perform this convolution for yourself   */
           /* before calling the function detectCorners.                      */

    int    xImageSize_p,         /* width of image                            */
    int    yImageSize_p,         /* height of image                           */

    int    halfPsgMaskSize_p,    /* The half of the mask size. The overall    */
           /* mask size, i.e., the size of the neighbourhood that is used to  */
           /* decide whether or not a candidate is a corner, then is          */
           /* (2*halfMaskSize + 1). Generally, the bigger masks give          */
           /* better results but the computation may be longer. The usual     */
           /* values of halfMaskSize vary from 4 to 7, which gives the overall*/
           /* size of the mask between 9x9 and 15x15 pixels.                  */

    float  angleThresh_p,        /* The threshold for the "angle of break" of */
           /* the boundary at the corner point. Only a point at which the     */
           /* boundary is broken more than is required by this threshold may  */
           /* be accepted as a corner. Usual value is approximately 0.5, which*/
           /* is an angle size in radians. As an explanation, I point out that*/
           /* due to noises, the values of small angles that are computed by  */
           /* the algorithm are always slightly higher than the angles you    */
           /* see in the images. The value of this threshold is more or less  */
           /* stable for all images. Therefore, you need not experiment too   */
           /* much unless you want to detect corners with a specific angle.   */
           /* Perhaps, you should choose a higher value of this threshold if  */
           /* you use small masks since in small masks, the precision of      */
           /* measuring the angles is generally lower than in greater masks.  */
           /* In some cases (in nice,not too noisy images), on the other hand,*/
           /* you may be able to detect even the corners with the break angle */
           /* less than 0.5. You can try the values down to approx. 0.3.)     */

    float  noiseGradSizeThresh_p,/* The threshold for the size of the gradient*/
           /* of brightness. All the values of the gradient size less than    */
           /* this threshold are considered to be a noise and the correspon-  */
           /* ding points are therefore excluded from processing. Higher      */
           /* values of this threshold contribute to the reduction of inf-    */
           /* luence of noise. At the same time, however, the less obvious    */
           /* corners may be missed. Remember that even in the synthetic      */
           /* images you have a noise that is caused by dividing the image    */
           /* into pixels. Typically, the value of this parameter varies      */
           /* between 0.04 and 0.08 of the image range (the difference between*/
           /* the maximal and minimal value of brightness in the image).      */
           /* Fine tuning of this threshold for your images is desirable. You */
           /* can start e.g. from the value (0.06*image range). After trying  */
           /* how it works, lower this value if you want that the less con-   */
           /* trast corners be detected. You should increase the value of this*/
           /* threshold, if the corners caused by noise are detected. If you  */
           /* decided to minimise the error, set the value of this threshold  */
           /* to the value giving the lowest possible error. The optimal value*/
           /* of this threshold should not depend too much on the the values  */
           /* of the remaining parameters. Let it be also pointed out that    */
           /* the higher values also lead to faster computation since the     */
           /* algorithm examines a lower number of candidates.                */

    float  apparenceThresh_p,    /* The threshold for the "apparence"         */
           /* (obviousness) of corner. The apparence combines the contrast,   */
           /* size and the shape of the possible corner area. Only the points */
           /* whose apparence is greater than this threshold can be accepted  */
           /* as corners. The value of this threshold must again be properly  */
           /* adjusted for your images. The typical value of this threshold   */
           /* varies usually between 0.0 and 5.0. You can start, for example, */
           /* from the value 2.0. If the algorithm detects too many corners,  */
           /* increase the value of this threshold and vice versa. We remark  */
           /* that the value of this theshold may be even negative (you can   */
           /* try a negative value if the detectors misses the T corners). We */
           /* recommend to experiment with the value of this threshold after  */
           /* preliminarily setting the previous threshold.                   */

    float  meanGradSizeThresh_p, /* The threshold for the mean value of the   */
           /* gradient magnitude over the area of corner. This threshold is   */
           /* used only for the final testing of the acceptability of the     */
           /* corners. If you do not require this test, set this value simply */
           /* to 0.0 (in this case, the decision is made on the basis of      */
           /* apparenceThresh_p) If, on the other hand, you want that the test*/
           /* be carried out, you should set this parameter to a value that is*/
           /* greater than the value of noiseGradSizeThresh_p ( simply: what  */
           /* is less than noiseGradSizeThresh_p is a noise, the mean value   */
           /* of the required gradient magnitude over the corner area should  */
           /* therefore be greater).                                          */

    float  inertiaRadiusThresh_p,/* The threshold for the radius of inertia of*/
           /* the corner area. The radius checks the size of the corner area. */
           /* Again, this threshold is used only for the final testing of the */
           /* acceptability of the corners. If you do not require this test,  */
           /* set this value simply to 0.0. If you want that the test be      */
           /* carried out, set this threshold to a value between, say, 1.0 and*/
           /* 3.0 (greater values mean that you want only "bigger" corners).  */

    float  sigmaD_p,             /* "Sigma" for the normal distribution       */
           /* of the probability density pd(). From the theoretical point     */
           /* of view, it follows that the value should be less than 1.0.     */
           /* Values between 0.7 and 1.0 were confirmed as optimal also       */
           /* experimentally. The value of 0.95 proved to be suitable for most*/
           /* images. You need not experiment with this value too much. Only  */
           /* if you want to obtain the absolutely best possible detection    */
           /* for your images you could make some trials. You should carry out*/
           /* them after preliminarily setting the values of the previously   */
           /* mentioned parameters. In the case of change, you should check   */
           /* the values of the remaining parameters again.                   */

    float  sigmaR_p,             /* "Sigma" for the Gaussian expressing the   */
           /* the function wr(), i.e., the weights depending on the distances */
           /* from the candidate that is just being processed. For the above  */
           /* mentioned sizes of the mask, use the values between 2.5 and 3.5,*/
           /* typically 3.0. Usually, the value is not critical. Again, you   */
           /* can check the value of this parameter, e.g., at the end, after  */
           /* you have found the values for all the remaining parameters.     */

    int    halfExtMaskSize_p,    /* This parameter says what is the size of   */
           /* the area in which it is checked whether the corner response     */
           /* function corr() has its maximum at the point just being tested. */
           /* Typical value of this parameter is 1, which means that the      */
           /* maximum is checked in the area of 3x3 pixels with the point     */
           /* being tested in its center. You should start with this value.   */
           /* Only if you have problems with multiple detections of the same  */
           /* corners, you could try to use a higher value of this parameter, */
           /* typically the value of 2 or 3. The value of this parameter must */
           /* always be less than or equal to the value of the parameter      */
           /* halfPsgMaskSize_p.                                              */

    int    options_p,            /* Here you can specify the actions that are */
           /* carried out optionally. You can use the following values:       */
           /*                                                                 */
           /* BIT 0: Sort the corners in the output cornerList according to   */
           /* their apparence.                                                */
           /*                                                                 */
           /* BIT 2: If the bit is set, the corner apparence is modified by   */
           /* determining the gradient-size signal-to-noise ratio in the      */
           /* neighbourhood of Q. If you do not use this option, the value    */
           /* of noiseGradSizeThresh_p is used as an estimation of the level  */
           /* of noise. If you use this option, the algorithm will try to     */
           /* estimate the level of noise more exactly by analysing the       */
           /* neighbourhood of Q. You can try to use this option if you want  */
           /* the apparence to correspond more exactly to the obviousness of  */
           /* corners as is perceived by humans. Please, take this option as  */
           /* experimantal (at the moment).                                   */

    int    *cornerList,          /* Here you pass the array into which the    */
           /* output is written. The x,y coordinates are written to this array*/
           /* for each corner. The function returns the number of corners that*/
           /* were found.                                                     */

    int    cornerListLen );      /* Here you say how long array for the       */
           /* corners you have. The length should be an even number (one item */
           /* for each coordinate). In case that more corners than            */
           /* cornerListLen/2 are found, the function returns -2. In this     */
           /* case, the cornerList contains the first cornerListLen/2 corners.*/

/* The function returns either the number of corners that were found or -1    */
/* if there was not enough memory to solve the task or -2 if the array        */
/* "cornerList" was not big enough for all the corners that were found.       */
/*============================================================================*/

#define SORT_CORNERS    1
#define CHECK_APPAR_SNR 2

#endif

